home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.cs.arizona.edu
/
ftp.cs.arizona.edu.tar
/
ftp.cs.arizona.edu
/
icon
/
newsgrp
/
group94a.txt
/
000010_icon-group-sender _Tue Jan 11 18:48:06 1994.msg
< prev
next >
Wrap
Internet Message Format
|
1994-08-19
|
6KB
Received: by cheltenham.cs.arizona.edu; Tue, 11 Jan 1994 12:52:10 MST
From: sperber@provence.informatik.uni-tuebingen.de (Michael Sperber [Mr. Preprocessor])
Message-Id: <9401111748.AA28891@provence.informatik.uni-tuebingen.de>
To: icon-group@cs.arizona.edu
Reply-To: sperber@informatik.uni-tuebingen.de
Subject: Icon and PTYs
Date: Tue, 11 Jan 94 18:48:06 +0100
Status: R
Errors-To: icon-group-errors@cs.arizona.edu
I posted about this a while ago, and back then I wrote a kludgy
solution called flush. I use it for controlling an interactive SML
compiler from an Icon program. The basic idea is that flush starts a
process on a tty, and forces all output to be flushed at each newline.
This means you can open(..,"p..") a file from Icon, redirect output to
a temp file an poll that file for output to arrive.
Problem is this is the first (and only) pty code I ever wrote. I've
tried to conform to the BSD docs that I have, but I'm not sure it runs
on anything but AIX. I'd be grateful if someone else could give this
a whirl and tell me what I need to change to make it run on other
architectures.
If there's interest, I could post the compiler driver also as an
example.
Since this project has shown me that Icon is - except for
pipe/socket/pty handling - ideally suited for controlling interactive
programs, I'd really appreciate Icon had an option to open that
would start a process on a pty pipe.
Cheers =8-} Chipsy
--snip, snip--
/* flush.c : execute the command on the command line
through a pty making sure all the output
from the command is flushed on a
line-by-line basis. */
/* $Log: flush.c,v $
* Revision 1.2 1993/07/20 13:41:30 sperber
* New version with pty code from rxvt.
* */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <termio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/wait.h>
static char rcsid[] = "$Id: flush.c,v 1.2 1993/07/20 13:41:30 sperber Exp sperber $";
int
main(int argc, char *argv[])
{
void pass_through(int, int);
static char ptynam[] = "/dev/ptyxx";
static char ttynam[] = "/dev/ttyxx";
struct termios ttmode;
int ptyfd, ttyfd;
int uid, gid;
unsigned char *s3, *s4;
int i;
int width, height;
static char ptyc3[] = "pqrstuvwxyz";
static char ptyc4[] = "0123456789abcdef";
unsigned char argv0[256];
int comm_pid;
/* First find a master pty that we can open.
*/
ptyfd = -1;
for (s3 = ptyc3; *s3 != 0; s3++)
{
for (s4 = ptyc4; *s4 != 0; s4++)
{
ptynam[8] = ttynam[8] = *s3;
ptynam[9] = ttynam[9] = *s4;
if ((ptyfd = open(ptynam, O_RDWR)) >= 0)
{
if (geteuid() == 0 || access(ttynam, R_OK|W_OK) == 0)
break;
else
{
close(ptyfd);
ptyfd = -1;
}
}
}
if (ptyfd >= 0)
break;
}
if (ptyfd < 0)
{
perror("Can't open a pseudo teletype");
return(-1);
}
fcntl(ptyfd, F_SETFL, O_NDELAY);
comm_pid = fork();
if (comm_pid < 0)
{
perror("Can't fork");
return(-1);
}
if (comm_pid == 0)
{
if (setsid() < 0)
perror("failed to set process group");
if ((ttyfd = open(ttynam, O_RDWR)) < 0)
{
perror("could not open slave tty");
exit(1);
}
uid = getuid();
dup2(ttyfd, fileno(stdin));
dup2(ttyfd, fileno(stdout));
dup2(ttyfd, fileno(stderr));
ttmode.c_iflag = BRKINT | IGNPAR | ISTRIP | ICRNL | IXON | IMAXBEL;
ttmode.c_oflag = OPOST | ONLCR;
ttmode.c_cflag = B9600 | PARENB | CS8 | CREAD;
ttmode.c_lflag = ISIG | IEXTEN | ICANON;
ttmode.c_cc[VINTR] = 003;
ttmode.c_cc[VQUIT] = 034;
ttmode.c_cc[VERASE] = 0177;
ttmode.c_cc[VKILL] = 025;
ttmode.c_cc[VEOF] = 004;
ttmode.c_cc[VEOL] = 000;
ttmode.c_cc[VEOL2] = 001;
ttmode.c_cc[VSTART] = 000;
ttmode.c_cc[VSTOP] = 021;
ttmode.c_cc[VSUSP] = 023;
ttmode.c_cc[VDSUSP] = 032;
ttmode.c_cc[VREPRINT] = 022;
ttmode.c_cc[VDISCRD] = 022;
ttmode.c_cc[VWERSE] = 017;
ttmode.c_cc[VLNEXT] = 027;
ioctl(0,TCSETS,(char *)&ttmode);
setgid(getgid());
setuid(uid);
execvp(argv[1], argv+1);
fprintf(stderr, "Couldn't execute %s",argv[1]);
exit(1);
}
pass_through(comm_pid, ptyfd);
exit(0);
}
void
pass_through(pid_t pid, int fd)
{
char in_char = '\0', out_char;
int n, in_pending = 0, term = 0, stdin_alive = 1;
int fd_stdin = fileno(stdin);
if (fcntl(fd_stdin, F_SETFL, fcntl(fd_stdin, F_GETFL, 0) | O_NONBLOCK) == -1)
{
perror("F_SETFL");
exit(1);
}
for (;;)
{
if (in_pending)
{
n = write(fd, &in_char, 1);
if (n == 1)
in_pending = 0;
}
if (stdin_alive && !in_pending)
{
n = read(fd_stdin, &in_char, 1);
if (n == -1)
{
if (errno != EAGAIN)
{
perror("unknown error during unblocked read");
exit(1);
}
}
else if (n == 1)
in_pending = 1;
else if (!n) /* EOF on stdin */
{
in_char = '\004';
in_pending = 1;
stdin_alive = 0;
}
}
term = waitpid(pid, 0, WNOHANG);
n = read(fd, &out_char, 1);
if (n < 1 && term)
{
fflush(stdout);
close(fd);
exit(0);
}
if (n == 1)
{
putchar(out_char);
if (out_char == '\n')
fflush(stdout);
}
}
}